package com.bkitmobile.kesu.android.service;


import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.bkitmobile.kesu.android.ClassInfo.Message;
import com.bkitmobile.kesu.android.ClassInfo.PlaceInfo;
import com.bkitmobile.kesu.android.ClassInfo.StoreMessage;
import com.bkitmobile.kesu.android.ClassInfo.UserConfig;
import com.bkitmobile.kesu.android.GUI.ChatActivity;
import com.bkitmobile.kesu.android.GUI.R;
import com.bkitmobile.kesu.android.connectServer.staticClass;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class UpdateLocationService extends Service{

	public static int UPDATE_LOCATION_DELAY = 0;
	public static final int DISTANCE = 500;
	public static final int CONFIG = 0;
	public static final int GENERAL = 1;
	public static final int STATE = 2;
	private UserConfig uConfig;
	private Alert alert;
	public static Location currentLocation;
	private String provider;
	private int alert_id = 0;
	private Handler controlHandler = new Handler();
	//private Alert alert;
	
	public class UpdateLocationBinder extends Binder {
        UpdateLocationService getService() {
            return UpdateLocationService.this;
        }
    }
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

	    // Define a set of criteria used to select a location provider.
	    criteria = new Criteria();
	    criteria.setAccuracy(Criteria.ACCURACY_FINE);
	    criteria.setAltitudeRequired(false);
	    criteria.setBearingRequired(true);
	    criteria.setCostAllowed(true);
	    criteria.setSpeedRequired(true);
	    criteria.setPowerRequirement(Criteria.POWER_HIGH);
	    provider = locationManager.getBestProvider(criteria, true);
	    currentLocation = locationManager.getLastKnownLocation(provider);
	    listMessage = new LinkedHashMap<String, StoreMessage>();
	    alert = new Alert(this);
	    staticClass.sendToService = new Handler(){
	    	public void handleMessage(android.os.Message m)
	    	{
	    		super.handleMessage(m);
		    		if (m.what == ChatActivity.CHAT_HANDLE){
		    		Bundle data = m.getData();
		    		String owner = data.getString("owner");
		    		String mess = data.getString("message");
		    		Log.d("message","saving:"+owner+":"+mess);
		    		addMessageFromMe(owner, mess);
	    		} else if (m.what == ChatActivity.CLOSE_HANDLE)
	    		{
	    			Bundle data = m.getData();
	    			String user = data.getString("user");
	    			listMessage.remove(user);
	    		} else if (m.what == CONFIG)
	    		{
	    			Bundle data = m.getData();
	    			setuConfig((UserConfig) data.getSerializable("config"));
	    			Log.d("log", "setted");
	    		} else if (m.what == STATE)
	    		{
	    			Bundle data = m.getData();
	    			uConfig.setLoadAround(data.getBoolean("near"));
	    			uConfig.setLoadFavorite(data.getBoolean("favorite"));
	    		} else if (m.what == GENERAL)
	    		{
	    			Bundle data = m.getData();
	    			uConfig.setAlertChat(data.getInt("alertChat"));
	    			uConfig.setAlertPlace(data.getInt("alertPlace"));
	    			uConfig.setListType((List<String>) data.getSerializable("listtype"));
	    		}
	    	}
	    };

	}

	private final LocationListener locationListener = new LocationListener(){

		@Override
		public void onLocationChanged(Location location) {
			// TODO Auto-generated method stub
			Log.d("change", "location change");
			UPDATE_LOCATION_DELAY = 2*60*1000;
			if (currentLocation != null && currentLocation.distanceTo(location) < DISTANCE)
				return;
			else {
				Log.d("send", "send change");
				double longtitude = location.getLongitude();
				double lattitude = location.getLatitude();
				staticClass.socket.println("<location><lat>"+lattitude+
						"<long>"+ longtitude);
				currentLocation = location;
			}
		}

		@Override
		public void onProviderDisabled(String provider) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void onProviderEnabled(String provider) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
			// TODO Auto-generated method stub
			
		}
		
	};
	private Criteria criteria;
	private LocationManager locationManager;
	@Override
	public void onStart(Intent intent, int startId) {
		// TODO Auto-generated method stub
		super.onStart(intent, startId);
		
		staticClass.isRunning = true;
		  
		new Thread(){
			public void run()
			{
				while (true)
				{	
					try {
						final String receive = staticClass.socket.readLine();
						if (receive == null) continue;
						else {
							Log.d("update", receive);
							controlHandler.post(new Runnable() {
								
								@Override
								public void run() {
									// TODO Auto-generated method stub
									setStringUpdate(receive);
								}
							});
						}
						provider = locationManager.getBestProvider(criteria, true);
					} catch (Exception e)
					{
						return;
					}
				}
			}
		}.start();
		
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, UPDATE_LOCATION_DELAY, DISTANCE, locationListener);
		locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, UPDATE_LOCATION_DELAY, DISTANCE, locationListener);
	}

	private final IBinder mBinder = new UpdateLocationBinder();
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return mBinder;
	}
	public void setUser(String user) {
		this.user = user;
	}
	public String getUser() {
		return user;
	}
	private String user;
	private String stringUpdate;
	private LinkedHashMap<String,StoreMessage> listMessage;
	public String getStringUpdate()
	{
		return stringUpdate;
	}
	
	public void addMessageFromMe(String owner,String mess)
	{
		StoreMessage store = listMessage.get(owner);
		Message message = new Message("me",mess);
		if (store == null)
		{
			store = new StoreMessage(owner);
			store.addMessage(message);
			listMessage.put(owner, store);
			
		} else 
		{
			store.addMessage(message);
		}
	}
	public LinkedHashMap<String,StoreMessage> getListChat()
	{
		return listMessage;
	}
	public void onCloseAChat(String id) {
		listMessage.remove(id);
	}
	public void setStringUpdate(String update)
	{
		this.stringUpdate = update;
		Log.d("receive", update);
		try {
			String decode = null;
			try {
				decode = URLDecoder.decode(update,"UTF-8");
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			JSONObject jObject = new JSONObject(decode);
			String id = jObject.getString("id");
			if (id.equals("alert"))
			{
				JSONArray jArr = new JSONArray(jObject.getString("places"));
				Log.d("receive", jArr.toString());
				List<PlaceInfo> lsInfo = new ArrayList<PlaceInfo>();
				for (int i = 0 ; i < jArr.length() ; i++)
				{
					JSONObject obj = jArr.getJSONObject(i);
					String type = obj.getString("type");
					String addr = obj.getString("addr");
					String name = obj.getString("name");
					double lat = obj.getDouble("lat");
					double lng = obj.getDouble("lng");
					PlaceInfo pInfo = new PlaceInfo(name,type,null,addr,lat,lng);
					lsInfo.add(pInfo);
				}
				if (lsInfo.size() > 0) 
				{
					if (alert == null) Log.d("alert", "null");
					if (uConfig == null) Log.d("uConfig", "null");
					alert.doAlertPlace(lsInfo, uConfig.getAlertPlace(),alert_id++);
				}
			}
		} catch (JSONException e)
		{
			if (update.startsWith("<chat>"))
			{
				String id = update.substring(
						update.indexOf("<from>")+6,
						update.lastIndexOf("<message>"));
				String mess = update.substring(
						update.lastIndexOf("<message>")+9);
				if (!ChatActivity.isStated)
	    			ChatActivity.isStated = true;
				StoreMessage store = listMessage.get(id);
				Message message = new Message(id,mess);
				Log.d("logging", "logging");
				if (!staticClass.isActivity)
					alert.doAlertChat(id,mess,uConfig.getAlertChat(),alert_id++);
				if (!staticClass.isActived.contains(id)) 
					Toast.makeText(this,this.getString(R.string.alert_msg)+" "+id
							, Toast.LENGTH_LONG).show();
				Log.d("logged", "logged");
				if (store == null)
				{
					store = new StoreMessage(id);
					store.addMessage(message);
					listMessage.put(id, store);
					
				} else 
				{
					store.addMessage(message);
				}
				
				if (staticClass.isChat)
				{
					Bundle data = new Bundle();
					data.putString("owner", id);
					data.putString("message", mess);
					android.os.Message messageSend = new android.os.Message();
					messageSend.setData(data);
					staticClass.chatHandler.sendMessage(messageSend);
				}
			}
			android.os.Message msg = new android.os.Message();
			Bundle data = new Bundle();
			data.putString("string", update);
			msg.setData(data);
			Log.e("data", update);
			msg.what = 100;
			staticClass.mHandler.sendMessage(msg);
		}
	}
	
	public void setuConfig(UserConfig uConfig) {
		this.uConfig = uConfig;
	}
	public UserConfig getuConfig() {
		return uConfig;
	}
	
}
